<?php
/**
 * @fileoverview    验证码接口
 * @author          chenglong@
 * @date            2011-09-15
 * @copyright       sina qing
 * @changelog
 * 2011-09-28 shaopu@ 代码重构
 * 2012-01-09 wangtao5@ 嵌入
 */
include_once $_SERVER['DOCUMENT_ROOT'] . '/__global.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/ml_controller.php';

class aj_verifyCode extends ml_controller{

    const WIDTH = 105;

    const HEIGHT = 40;

    /**
     * 验证码长度
     * @var number
     */
    const LENGTH = 5;

    

    private $session = null;
    public $_pageInfo;

    /**
     * 初始化POST数据
     *
     */
    public function initParam(){
        $this->session = self::getSession();
        // 标志, 为了同时在多个地方使用验证码而设置
        $this->_pageInfo['sign'] = empty($_GET['sign']) ? 'default' : $_GET['sign'];
        // verifycode
        $this->_pageInfo['code'] = empty($_GET['code']) ? '' : $_GET['code'];
        $this->_pageInfo['code'] = trim($this->_pageInfo['code']);
    }

    /**
     * 检测POST数据
     *
     */
    public function checkParam(){
        $this->check_referer();
        if (isset($this->_pageInfo['sign']{20})){
            $this->_pageInfo['sign'] = substr($this->_pageInfo['sign'], 0, 20);
        }
        if (trim($this->_pageInfo['code']) != ''){ //如果是验证验证码是否正确
            if ($this->checkVerify($this->_pageInfo['code'], $this->_pageInfo['sign'])){
                $this->api_output(ML_RCODE_SUCC , null , '验证码正确');
            }else{
                $this->api_output(ML_RCODE_FAIL , null , '验证码不正确');
            }
        }
    }

    private function checkVerify($verifyCode, $sign){
        if (strlen($verifyCode) != self::LENGTH){
            return false;
        }
        return $this->session->getVal('verify_' . $sign) == $verifyCode;
    }

    /**
     * 执行业务逻辑
     *
     */
    public function main(){
        $verifyCode = substr(str_shuffle('abcdefghijkmnpqrstuvwxyz23456789'), 0, self::LENGTH);
        $this->session->setVal('verify_' . $this->_pageInfo['sign'], $verifyCode);
        $this->session->save();
        header('Content-type: image/jpeg');
        $this->outputImage($verifyCode);
    }

    /**
     * 输出验证码图片
     * @param 验证码 $code
     */
    private function outputImage($code){
        //files needed
        $ffiles[0] = SYSDEF_TTF_ROOT_PATH . '/bookos.ttf';
        $ffiles[1] = SYSDEF_TTF_ROOT_PATH . '/cour.ttf';
        $ffiles[2] = SYSDEF_TTF_ROOT_PATH . '/gothic.ttf';
        $ffiles[3] = SYSDEF_TTF_ROOT_PATH . '/georgia.ttf';
        //omit return value
        //create image
        $img = imagecreatetruecolor(self::WIDTH, self::HEIGHT);
        imagefill($img, 0, 0, imagecolorallocate($img, 255, 255, 255));
        //get the index or the closest value of assigned color
        $colors[0] = imagecolorresolve($img, 255, 255, 255); //white
        $colors[1] = imagecolorresolve($img, 0, 0, 0); //black
        $colors[2] = imagecolorresolve($img, 9, 9, 53);
        $colors[3] = imagecolorresolve($img, 53, 9, 9);
        $colors[4] = imagecolorresolve($img, 10, 53, 10);
        $colors[5] = imagecolorresolve($img, 53, 52, 58);
        $colors[6] = imagecolorresolve($img, 41, 39, 29);
        $colors[7] = imagecolorresolve($img, 41, 44, 14);
        $colors[8] = imagecolorresolve($img, 16, 51, 54);
        $colors[9] = imagecolorresolve($img, 34, 54, 27);
        $colors[10] = imagecolorresolve($img, 71, 33, 16);
        $x = 8;
        $y = 30;
        $fakeimg = imagecreate(self::WIDTH, self::HEIGHT);
        //draw some confusion lines
        for ($i = 0; $i < strlen($code); $i++){
            imagesetthickness($img, 3 * $i);
            $line_color = imagecolorallocate($img, rand(150, 255), rand(150, 255), rand(150, 255));
            //draw a line
            imageline($img, rand() % self::WIDTH, rand() % self::HEIGHT, rand() % self::WIDTH, rand() % self::HEIGHT, $line_color);
        }
        $angle_rand = mt_rand(1,9)*100;
        for ($i = 0; $i < strlen($code); $i++){
            $size = $this->getrand(18, 25);
            $angle = $this->getrand(-1000+$angle_rand, 1000+$angle_rand) * M_PI / 180;
            $nFont = $this->getrand(0, count($ffiles) - 1);
            //can not user colors[0](white), number won't be shown well in white
            $nColor = $this->getrand(1, count($colors) - 1);
            $lastpos = array_fill(0, 7, 0);
            //draw virtually
            $lastpos = imagettftext($fakeimg, $size, $angle, 0, 0, 0, $ffiles[$nFont], $code[$i]);
            if ($lastpos[0] > $lastpos[6]){
                $leftlean = TRUE;
            }else{
                $leftlean = FALSE;
            }
            $drift_x = $leftlean ? $lastpos[0] - $lastpos[6] : 0;
            //draw a real number of pincode
            $lastpos = imagettftext($img, $size, $angle, $x, $y, $colors[$nColor], $ffiles[$nFont], $code[$i]);
            //$x += $leftlean ? $lastpos[2] - $lastpos[6] : $lastpos[4] - $lastpos[0] + 1;
            //$x -= mt_rand(2,5);
            
            $x_plus = 0;
            if(in_array(strtolower($code[$i]),array('m','w')))
                $x_plus = mt_rand(2,5);
            else if((in_array(strtolower($code[$i]),array('i','j','t')))) 
                $x_plus = mt_rand(-1,-3);
                
                
            $x += 10+ceil($size/5)+$x_plus;
            
        }
        for ($i = 0; $i < intval(self::WIDTH * self::HEIGHT / 70); $i++){
            //draw a pixel
            imagesetpixel($img, rand() % self::WIDTH, rand() % self::HEIGHT, $colors[1]);
        }
        imagejpeg($img);
        imagedestroy($img);
    }

    private function getrand($min, $max){
        $n = (double)rand();
        $n = $min + ((double)($max - $min + 1.0) * ($n / (getrandmax() + 1.0)));
        return $n;
    }
}
$verify = new aj_verifyCode();
